package map;

import java.util.Iterator;

/**
 * @author Yuri Denison
 * @since 08.08.11
 */
public class List<K, V> implements Iterable<List.Cell> {
    static class Cell<K, V> {
        private K key;
        private V value;
        private Cell<K, V> next;

        public Cell() {
            next = null;
        }

        public V getValue() {
            return value;
        }

        public K getKey() {
            return key;
        }
    }

    private Cell<K, V> cur;
    private Cell<K, V> root;

    public List() {
        cur = new Cell<K, V>();
        root = cur;
    }

    public boolean isEmpty() {
        return root.next == null;
    }

    public V add(K key, V value) {
        Cell<K, V> cell = root;
        while (cell.next != null) {
            if (cell.key.equals(key)) {
                V prevValue = cell.value;
                cell.value = value;
                return prevValue;
            }
            cell = cell.next;
        }

        cur.key = key;
        cur.value = value;
        Cell<K, V> cell1 = new Cell<K, V>();
        cur.next = cell1;
        cur = cell1;
        return null;
    }

    public int size() {
        int size = 0;
        Cell<K, V> cell = root;
        while (cell.next != null) {
            size++;
            cell = cell.next;
        }
        return size;
    }

    public V get(K key) {
        Cell<K, V> cell = root;
        while (cell.next != null) {
            if (cell.key.equals(key)) {
                return cell.value;
            }
            cell = cell.next;
        }
        return null;
    }

    public V remove(K key) {
        if (root.key.equals(key)) {
            V v = root.value;
            root = root.next;
            return v;
        }

        Cell<K, V> cell = root;
        while (cell.next.next != null) {
            if (cell.next.key.equals(key)) {
                cell.next = cell.next.next;
                return cell.next.value;
            }
            cell = cell.next;
        }
        return null;
    }

    public void clear() {
        root.next = null;
        cur = root;
    }

    public boolean containsValue(V val) {
        Cell<K, V> cell = root;
        while (cell.next != null) {
            if (cell.value.equals(val))
                return true;
            cell = cell.next;
        }
        return false;
    }

    public Iterator<Cell> iterator() {
        return new Iterator<Cell>() {
            Cell<K, V> cur1 = root;

            public boolean hasNext() {
                return cur1 != null && cur1.next != null;
            }

            public void remove() {
                Cell<K, V> cell = cur1.next;
                List.this.remove(cur1.key);
                cur1 = cell;
            }

            public Cell next() {
                Cell<K, V> c = cur1;
                cur1 = cur1.next;
                return c;
            }
        };
    }
}